package com.contract.commonlib.base

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import cn.woochen.comlib.config.IBaseView
import cn.woochen.comlib.loadinglayout.EmptyCallBack
import cn.woochen.comlib.loadinglayout.ErrorCallback
import cn.woochen.comlib.loadinglayout.LoadingCallBack
import cn.woochen.comlib.loadinglayout.LoadingHasContentCallBack
import com.contract.commonlib.refresh.MyRefreshLayout
import com.contract.commonlib.refresh.NoMoreDataFootView
import com.kingja.loadsir.core.LoadService
import com.kingja.loadsir.core.LoadSir
import java.lang.reflect.ParameterizedType
import java.lang.reflect.Type

abstract class BaseFragment<DB : ViewDataBinding, VM : BaseViewModel> : Fragment(), IBaseView {

    protected val mContext by lazy {
        requireActivity()
    }

    protected lateinit var mBinding: DB
        private set

    protected lateinit var mViewModel: VM

    protected lateinit var loadService: LoadService<*>
    protected open val footView by lazy {
        NoMoreDataFootView(mContext);
    }
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        mBinding = DataBindingUtil.inflate(inflater, setContentView(), container, false)
        mViewModel = createViewModel()
        loadService = LoadSir.getDefault().register(mBinding.root){
            onReload()
        }
        registerNecessaryObserver()
        initListener()
        initRefresh()
        initData()
        //       return mBinding.root
        return loadService.loadLayout
    }
    protected open fun onReload(){}
    protected open fun initRefresh() {}
    private fun createViewModel(): VM {
        return ViewModelProvider(this).get(getVmClazz(this))
    }

    protected abstract fun setContentView(): Int

    protected open fun initListener() {}

    /**
     * 获取任意对象的泛型信息，返回一个继承了BaseViewModel的字节码对象
     */
    private fun getVmClazz(obj: Any): Class<VM> {
        var cls: Class<*>? = obj.javaClass
        var vmClass: Class<VM>? = null
        while (vmClass == null && cls != null) {
            vmClass = getVMClass(cls)
            cls = cls.superclass
        }
        if (vmClass == null) {
            vmClass = BaseViewModel::class.java as Class<VM>
        }
        return vmClass
    }

    private fun getVMClass(cls: Class<*>): Class<VM>? {
        val type: Type? = cls.genericSuperclass
        if (type is ParameterizedType) {
            val types: Array<Type> = type.actualTypeArguments
            for (t in types) {
                if (t is Class<*>) {
                    val vmClass = t
                    if (BaseViewModel::class.java.isAssignableFrom(vmClass)) {
                        return vmClass as Class<VM>
                    }
                } else if (t is ParameterizedType) {
                    val rawType: Type = t.rawType
                    if (rawType is Class<*>) {
                        val vmClass = rawType
                        if (BaseViewModel::class.java.isAssignableFrom(vmClass)) {
                            return vmClass as Class<VM>
                        }
                    }
                }
            }
        }
        return null
    }

    /**
     * 网络请求数据
     */
    protected open fun requestData() {}

    protected abstract fun initData()


    override fun showContent() {
        loadService.showSuccess()
    }

    override fun showEmpty() {
        loadService.showCallback(EmptyCallBack::class.java)
    }

    override fun showLoading(showContent: Boolean,content:String) {
        if (showContent) {
            loadService.showCallback(LoadingHasContentCallBack(content)::class.java)
        } else {
            loadService.showCallback(LoadingCallBack::class.java)
        }
    }

    override fun showError() {
        loadService.showCallback(ErrorCallback::class.java)
    }

    open fun beginRefreshing(bgRefres: MyRefreshLayout) {
        bgRefres.autoRefresh()
    }

    open fun endRefreshing(bgRefres: MyRefreshLayout) {
        bgRefres.finishRefresh()
    }

    open fun endLoadingMore(bgRefres: MyRefreshLayout) {
        bgRefres.finishLoadMore()
    }

    open fun endLoad(pageNum: Int, bgRefresh: MyRefreshLayout){
        if (pageNum==1){
            endRefreshing(bgRefresh)
        }else{
            endLoadingMore(bgRefresh)
        }
    }

    open fun setDataLoadFinish(pageNum: Int, size: Int, bgRefresh: MyRefreshLayout) {
        if (pageNum == 1) {
            if (size > 0) {
                footView.footViewState(NoMoreDataFootView.FOOT_HIDE)
            } else {
                footView.footViewState(NoMoreDataFootView.FOOT_NO_DATA)
                bgRefresh.finishLoadMoreWithNoMoreData()
            }
            endRefreshing(bgRefresh)
        } else {
            if (size <= 0) {
                footView.footViewState(NoMoreDataFootView.FOOT_NO_MORE)
                bgRefresh.finishLoadMoreWithNoMoreData()
            } else {
                footView.footViewState(NoMoreDataFootView.FOOT_HIDE)
                endLoadingMore(bgRefresh)
            }
        }
    }
    open fun setDataLoadFinish(size: Int, bgRefresh: MyRefreshLayout) {
        if (size > 0) {
            footView.footViewState(NoMoreDataFootView.FOOT_NO_MORE)
        } else {
            footView.footViewState(NoMoreDataFootView.FOOT_NO_DATA)
        }
        endRefreshing(bgRefresh)
    }
    /**
     * 注册 UI 事件
     */
    protected open fun registerNecessaryObserver() {
        mViewModel.loadingChange.showDialog.observe(this, Observer {
            showLoading(it)
        })
        mViewModel.loadingChange.dismissDialog.observe(this, Observer {
            if (it){
                showContent()
            }else{
                showError()
            }
        })
    }

}